// adodb_impl.h
#ifndef BSLIB_DB_ADODB_IMPL_H_
#define BSLIB_DB_ADODB_IMPL_H_

#ifdef _WIN64
	#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace raw_interfaces_only
#else
	#import "libid:2A75196C-D9EB-4129-B803-931327F72D5C" no_namespace raw_interfaces_only
#endif // _WIN64

#include "adodb.h"
#include <vector>
#include <sqltypes.h>

class ADODB::Impl
{
public:
	Impl();
	~Impl();

	bool Connect(const wchar_t* ip, const wchar_t* db, const wchar_t* user, const wchar_t* password, unsigned long timeout = 0);
	bool Connect(const wchar_t* connection_string, unsigned long timeout = 0);
	bool Disconnect();

	bool SetCommand(CommandType type, const wchar_t* sql, unsigned long timeout);
	bool SetParameter(_variant_t column, ParameterDirection direction, DataType type, void* buffer, std::size_t size);
	bool ExecuteCommand();
	
	bool GetRowCount(unsigned long& count);
	bool GetRowSize(std::size_t& size);
	bool GetColumnCount(short& count);

	bool GetColumnType(const _variant_t& column, DataType& type);
	bool GetColumnActualSize(const _variant_t& column, std::size_t& size);
	bool GetColumnDefinedSize(const _variant_t& column, std::size_t& size);
	bool GetColumnData(const _variant_t& column, DataType type, void* buffer, std::size_t buffer_size, std::size_t* actual_size);

	bool SetCursorLocation(CursorLocation location);
			
	bool IsRowEnd();
	bool MoveNextRow();

	bool IsConnected();
	
private:
	class OutputParameter
	{
	public:
		OutputParameter(const _variant_t& column, DataType type, void* buffer, std::size_t buffer_size)
			: column_(column), type_(type), buffer_(buffer), buffer_size_(buffer_size) {}

		const _variant_t& column() const { return column_; }
		DataType type() const { return type_; }
		void* buffer() const { return buffer_; }
		std::size_t buffer_size() const { return buffer_size_; }
		
	private:
		_variant_t column_;
		DataType type_;
		void* buffer_;
		std::size_t buffer_size_;
	};

	bool CleanupCommand();
	bool GetParameterData(const _variant_t& column, DataType type, void* buffer, std::size_t buffer_size, std::size_t* actual_size);
	bool GetVariantData(_variant_t& variant, void* buffer, std::size_t buffer_size, std::size_t* actual_size);
		
	static bool com_init_;
	_Connection* connection_;
	_Command* command_;
	CommandTypeEnum command_type_;
	_Recordset* recordset_;
	Parameters* parameters_;
	Fields* fields_;
	typedef std::vector<OutputParameter*> OUTPUT_PARAMETERS;
	OUTPUT_PARAMETERS output_parameters_;
	TIMESTAMP_STRUCT timestamp_;
};

#endif // BSLIB_DB_ADODB_IMPL_H_